library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ──────────────────────────────────────────────────────────────── tidyverse 1.3.2 ──✔ ggplot2 3.3.6     ✔ purrr   0.3.4
✔ tibble  3.1.8     ✔ dplyr   1.0.9
✔ tidyr   1.2.0     ✔ stringr 1.4.0
✔ readr   2.1.2     ✔ forcats 0.5.1── Conflicts ─────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
library(gganimate)
library(ggtern)
Registered S3 methods overwritten by 'ggtern':
  method           from   
  grid.draw.ggplot ggplot2
  plot.ggplot      ggplot2
  print.ggplot     ggplot2
--
Remember to cite, run citation(package = 'ggtern') for further info.
--

Attaching package: ‘ggtern’

The following objects are masked from ‘package:ggplot2’:

    aes, annotate, ggplot, ggplot_build, ggplot_gtable, ggplotGrob, ggsave, layer_data,
    theme_bw, theme_classic, theme_dark, theme_gray, theme_light, theme_linedraw,
    theme_minimal, theme_void
obp_dynatts_df <- read_csv("resources/3_obp_dynatts_df.csv")
Rows: 106657 Columns: 24── Column specification ─────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr   (2): SECCODE, ATT
dbl  (20): NO, OBPLOTNO, VAL, SHAREBAL, BPROFIT, SPROFIT, OBPMINTPRICE, OBPMAXTPRICE, CBOVOLtdcs, CSO...
dttm  (1): DATETIMEMLLS
date  (1): DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
obp_dynatts_df
OBPlots_df <- read_csv("resources/2_OBPlots_df.csv")
Rows: 106657 Columns: 12── Column specification ─────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (2): SECCODE, BUYSELL
dbl  (9): NO, TIME, ORDERNO, ACTION, PRICE, VOLUME, TRADENO, TRADEPRICE, OBPLOTNO
date (1): DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
OBPlots_df
obp_dynatts_no_df <- left_join(obp_dynatts_df, 
                            OBPlots_df %>% select(NO, TIME), 
                            by = "NO") %>% 
  mutate(TIMEm = as.character(as.integer(TIME / 100000)),
         TIME = as.character(TIME / 1000)) %>% 
  select(NO, SECCODE, DATETIMEMLLS, DATE, TIME, TIMEm, OBPLOTNO, 
         ATT, VAL, SHAREBAL, BPROFIT, SPROFIT, OBPMINTPRICE, OBPMAXTPRICE,
         CBOVOLtdcs, CSOVOLtdcs, BOVOLtdcs, SOVOLtdcs, BTVOLtdcs, STVOLtdcs,
         CBOVOLobpcs, CSOVOLobpcs, BOVOLobpcs, SOVOLobpcs, BTVOLobpcs, STVOLobpcs)
obp_dynatts_no_df
obp_dynatts_no_price_df <- left_join(obp_dynatts_no_df, 
                                     OBPlots_df %>% select(NO, PRICE, TRADEPRICE, VOLUME), 
                                     by="NO")
obp_dynatts_no_price_df
temp_df <- obp_dynatts_no_df %>% 
  spread(key = ATT, value = VAL) %>% 
  select(TIME, TIMEm, NO, OBPLOTNO, SOVOL, SOVOLtdcs, SOVOLobpcs)
  # filter(OBPLOTNO == 129)
temp_df
ggplot(data = temp_df) + 
  # geom_point(mapping = aes(x = NO, y = SOVOL), color = "red") +
  # geom_point(mapping = aes(x = NO, y = SOVOLtdcs), color = "green") +
  geom_point(mapping = aes(x = NO, y = SOVOLobpcs), color = "blue")

# sm - val median by second

temp_sm_df <- temp_df %>% 
  group_by(TIMEm) %>% 
  summarise(SOVOLobpcs = median(SOVOLobpcs))
temp_sm_df
ggplot(data = temp_sm_df) + 
  geom_point(mapping = aes(x = TIMEm, y = SOVOLobpcs), color = "blue")

obp_atts_by_obp_df <- read_csv("resources/4_obp_atts_by_obp_df.csv")
Rows: 2028 Columns: 8── Column specification ─────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (2): SECCODE, BUYSELLOBP
dbl  (4): OBPLOTNO, BUYSELLYIELD, OBPTDVOLRATIO, MINMAXRATIO
lgl  (1): TRADESNOTRADES
date (1): DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
obp_atts_by_obp_df
obp_atts_by_obp_df %>% arrange(desc(MINMAXRATIO))
# obp_atts_by_obp_df %>% arrange(BUYSELLYIELD)
pbegin <- obp_dynatts_no_price_df %>% 
  .$DATETIMEMLLS %>% 
  min(.)
print(pbegin)
[1] "2007-10-08 10:30:00 UTC"
pend <- obp_dynatts_no_price_df %>% 
  .$DATETIMEMLLS %>% 
  max(.) 
print(pend)
[1] "2007-10-08 17:45:00 UTC"
pcolor <- function(att, plotno) {
  color = ""
  if (plotno == plotno) {
    if (att == 'BOVOL') color = "green"
    else if (att == 'SOVOL') color = "red"
    else if (att == 'BTVOL' | att == 'STVOL') color = "blue"
    else color = "white"
  } else {
    if (att == 'BOVOL') color = "green"#"aquamarine"
    else if (att == 'SOVOL') color = "red"#"coral"
    else if (att == 'BTVOL' | att == 'STVOL') color = "blue" #"cadetblue1"
    else color = "white"
  }
  # print(paste(att, plotno, color))
  return(color)
}
td_df <- obp_dynatts_no_price_df %>% 
  filter((DATETIMEMLLS >= pbegin & DATETIMEMLLS <= pend) & (ATT == "BOVOL" | ATT == "SOVOL" | ATT == "BTVOL" | ATT == "STVOL") & PRICE > 2145.0 & PRICE < 2195.0) %>%
  mutate(pcolor = map2(ATT, OBPLOTNO, ~pcolor(.x, .y)) %>% unlist())
td_df
# curplotno = 302
curplotno = 1869
# curplotno = 52

pbegin <- obp_dynatts_no_price_df %>%
  filter(OBPLOTNO == curplotno) %>%
  .$DATETIMEMLLS %>%
  min(.)

pend <- obp_dynatts_no_price_df %>%
  filter(OBPLOTNO == curplotno) %>%
  .$DATETIMEMLLS %>%
  max(.)

pcolor <- function(att, plotno) {
  color = ""
  if (plotno == curplotno) {
    if (att == 'BOVOL') color = "green"
    else if (att == 'SOVOL') color = "red"
    else if (att == 'BTVOL' | att == 'STVOL') color = "#8031A7" #"blue"
    else color = "white"
  } else {
    if (att == 'BOVOL') color = "aquamarine"
    else if (att == 'SOVOL') color = "coral"
    else if (att == 'BTVOL' | att == 'STVOL') color = "#004481" #"cadetblue1"
    else color = "white"
  }
  # print(paste(att, plotno, color))
  return(color)
}

pshape <- function(att, plotno) {
  color = ""
  if (plotno == curplotno) {
    shape = 16
  } else {
    shape = 4
  }
  # print(paste(att, plotno, color))
  return(shape)
}

psize <- function(att, plotno) {
  color = ""
  if (plotno == curplotno) {
    size = 1.0
  } else {
    size = 0.5
  }
  # print(paste(att, plotno, color))
  return(size)
}

plot_df_without_rep_by_vol <- obp_dynatts_no_price_df %>% 
  filter((DATETIMEMLLS >= pbegin & DATETIMEMLLS <= pend) & (ATT == "BOVOL" | ATT == "SOVOL" | ATT == "BTVOL" | ATT == "STVOL") & PRICE > 2145.0 & PRICE < 2205.0) %>%
  mutate(pcolor = map2(ATT, OBPLOTNO, ~pcolor(.x, .y)) %>% unlist(),
         pshape = map2(ATT, OBPLOTNO, ~pshape(.x, .y)) %>% unlist(),
         psize = map2(ATT, OBPLOTNO, ~psize(.x, .y)) %>% unlist())
plot_df_without_rep_by_vol %>% filter(OBPLOTNO == curplotno)
# plot_df <-  with(plot_df_without_rep_by_vol,
#                  plot_df_without_rep_by_vol[rep(1:nrow(plot_df_without_rep_by_vol),
#                                                 as.integer(log(VOLUME, base = 1.01)) + 1),])
plot_df <-  plot_df_without_rep_by_vol
# dt1 <- td_df %>% filter(ATT != "BTVOL" & ATT != "STVOL")
# dt2 <- td_df %>% filter(ATT == "BTVOL" | ATT == "STVOL")
# ggplot() + 
#   geom_point(data = dt1, mapping = aes(x = TIME, y = PRICE), color = dt1$pcolor, shape = 4, size = 0.5) +
#   geom_point(data = dt2, mapping = aes(x = TIME, y = PRICE), color = dt2$pcolor, shape = 4, size = 0.5)
dt11 <- plot_df %>% filter(OBPLOTNO != curplotno & ATT != "BTVOL" & ATT != "STVOL")
dt12 <- plot_df %>% filter(OBPLOTNO != curplotno & (ATT == "BTVOL" | ATT == "STVOL"))
dt21 <- plot_df %>% filter(OBPLOTNO == curplotno & ATT != "BTVOL" & ATT != "STVOL")
dt22 <- plot_df %>% filter(OBPLOTNO == curplotno & (ATT == "BTVOL" | ATT == "STVOL"))
ggplot() + 
  geom_point(data = dt11, mapping = aes(x = TIME, y = PRICE), 
             color = dt11$pcolor, shape = dt11$pshape, size = dt11$psize) + 
  geom_point(data = dt12, mapping = aes(x = TIME, y = PRICE), 
             color = dt12$pcolor, shape = dt12$pshape, size = dt12$psize) + 
  geom_point(data = dt21, mapping = aes(x = TIME, y = PRICE), 
             color = dt21$pcolor, shape = dt21$pshape, size = dt21$psize) + 
  geom_point(data = dt22, mapping = aes(x = TIME, y = PRICE), 
             color = dt22$pcolor, shape = dt22$pshape, size = dt22$psize)

dt_s <- plot_df %>% filter(OBPLOTNO != curplotno & ATT == "SOVOL")
dt_b <- plot_df %>% filter(OBPLOTNO != curplotno & ATT == "BOVOL")
dt_t <- plot_df %>% filter(OBPLOTNO != curplotno & (ATT == "BTVOL" | ATT == "STVOL"))
dt_cp_sb <- plot_df %>% filter(OBPLOTNO == curplotno & ATT != "BTVOL" & ATT != "STVOL")
dt_cp_t <- plot_df %>% filter(OBPLOTNO == curplotno & (ATT == "BTVOL" | ATT == "STVOL"))

# dt_s <- plot_df %>% filter(ATT == "SOVOL")
# dt_b <- plot_df %>% filter(ATT == "BOVOL")
# dt_t <- plot_df %>% filter(ATT == "BTVOL" | ATT == "STVOL")
# ggplot(dt_s, aes(x = NO, y = PRICE)) +
#   stat_density2d(mapping = aes(fill = ..level..), alpha = .5,
#                  geom = "polygon", data = dt_s) + 
#   scale_fill_viridis_c() + 
#   # theme(legend.position = 'none') +
#   scale_fill_distiller(palette = 'Reds')
# ggplot(dt_b, aes(x = NO, y = PRICE)) +
#   stat_density2d(mapping = aes(fill = ..level..), alpha = .5,
#                  geom = "polygon", data = dt_b) + 
#   scale_fill_viridis_c() + 
#   # theme(legend.position = 'none') +
#   scale_fill_distiller(palette = 'Greens')
ggplot(bind_rows(tibble(dt_s, gr = "s"), tibble(dt_b, gr = "b")), aes(x = NO, y = PRICE)) +
  stat_density2d(geom = "polygon", aes(fill = gr, alpha = ..level..)) + 
  scale_fill_manual(values=c("s"="#FF0000", "b"="#00FF00")) +
  geom_point(data = dt_t, mapping = aes(x = NO, y = PRICE), 
             color = dt_t$pcolor, shape = dt_t$pshape, size = dt_t$psize) +
  geom_point(data = dt_cp_sb, mapping = aes(x = NO, y = PRICE), 
             color = dt_cp_sb$pcolor, shape = dt_cp_sb$pshape, size = dt_cp_sb$psize) +
  geom_point(data = dt_cp_t, mapping = aes(x = NO, y = PRICE), 
             color = dt_cp_t$pcolor, shape = dt_cp_t$pshape, size = dt_cp_t$psize)

ggplot(bind_rows(tibble(dt_b, gr = "s"), tibble(dt_s, gr = "b")), aes(x = NO, y = PRICE)) +
  stat_density2d(geom = "polygon", aes(fill = gr, alpha = ..level..)) + 
  scale_fill_manual(values=c("b"="#FF0000", "s"="#00FF00")) +
  geom_point(data = dt_t, mapping = aes(x = NO, y = PRICE), 
             color = dt_t$pcolor, shape = dt_t$pshape, size = dt_t$psize) +
  geom_point(data = dt_cp_sb, mapping = aes(x = NO, y = PRICE), 
             color = dt_cp_sb$pcolor, shape = dt_cp_sb$pshape, size = dt_cp_sb$psize) +
  geom_point(data = dt_cp_t, mapping = aes(x = NO, y = PRICE), 
             color = dt_cp_t$pcolor, shape = dt_cp_t$pshape, size = dt_cp_t$psize)

ggplot(bind_rows(tibble(dt_s, gr = "s"), tibble(dt_b, gr = "b")), aes(x = NO, y = PRICE)) +
  stat_density2d(geom = "density2d", aes(color = gr)) + 
  scale_color_manual(values=c("s"="#FF0000", "b"="#00FF00")) +
  geom_point(data = dt_t, mapping = aes(x = NO, y = PRICE), 
             color = dt_t$pcolor, shape = dt_t$pshape, size = dt_t$psize) +
  geom_point(data = dt_cp_sb, mapping = aes(x = NO, y = PRICE), 
             color = dt_cp_sb$pcolor, shape = dt_cp_sb$pshape, size = dt_cp_sb$psize) +
  geom_point(data = dt_cp_t, mapping = aes(x = NO, y = PRICE), 
             color = dt_cp_t$pcolor, shape = dt_cp_t$pshape, size = dt_cp_t$psize) +
  theme_bw()

td_first_30minute_df <- td_df %>% 
  filter(TIME < 1100000)
td_first_30minute_df
static_plot <- ggplot() + 
  geom_point(data = td_first_30minute_df, 
             mapping = aes(x = TIME, y = PRICE), 
             color = td_first_30minute_df$pcolor, 
             shape = 4, 
             size = 0.5)
static_plot

dens_plot <- ggplot(td_first_30minute_df, aes(x = NO, y = PRICE)) +
  stat_density2d(aes(fill = ..level..), alpha = .5,
                 geom = "polygon", data = td_first_30minute_df) + 
  scale_fill_viridis_c() + 
  theme(legend.position = 'none')
dens_plot

# animation <- static_plot +
#   transition_states(NO, transition_length = 1, state_length = 1) +
#   ease_aes('linear') +
#   shadow_mark() +
#   view_follow()
# animation
# obp30mins_gif <- animate(animation, 
#                  fps = 10, 
#                  duration = 10,
#                  width = 800, height = 400, 
#                  renderer = gifski_renderer("./2gif/obp30mins.gif"))
LS0tDQp0aXRsZTogIk9CUGxvdHMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShnZ2FuaW1hdGUpDQpsaWJyYXJ5KGdndGVybikNCmBgYA0KDQoNCmBgYHtyfQ0Kb2JwX2R5bmF0dHNfZGYgPC0gcmVhZF9jc3YoInJlc291cmNlcy8zX29icF9keW5hdHRzX2RmLmNzdiIpDQpvYnBfZHluYXR0c19kZg0KYGBgDQoNCmBgYHtyfQ0KT0JQbG90c19kZiA8LSByZWFkX2NzdigicmVzb3VyY2VzLzJfT0JQbG90c19kZi5jc3YiKQ0KT0JQbG90c19kZg0KYGBgDQoNCmBgYHtyfQ0Kb2JwX2R5bmF0dHNfbm9fZGYgPC0gbGVmdF9qb2luKG9icF9keW5hdHRzX2RmLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBPQlBsb3RzX2RmICU+JSBzZWxlY3QoTk8sIFRJTUUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJOTyIpICU+JSANCiAgbXV0YXRlKFRJTUVtID0gYXMuY2hhcmFjdGVyKGFzLmludGVnZXIoVElNRSAvIDEwMDAwMCkpLA0KICAgICAgICAgVElNRSA9IGFzLmNoYXJhY3RlcihUSU1FIC8gMTAwMCkpICU+JSANCiAgc2VsZWN0KE5PLCBTRUNDT0RFLCBEQVRFVElNRU1MTFMsIERBVEUsIFRJTUUsIFRJTUVtLCBPQlBMT1ROTywgDQogICAgICAgICBBVFQsIFZBTCwgU0hBUkVCQUwsIEJQUk9GSVQsIFNQUk9GSVQsIE9CUE1JTlRQUklDRSwgT0JQTUFYVFBSSUNFLA0KICAgICAgICAgQ0JPVk9MdGRjcywgQ1NPVk9MdGRjcywgQk9WT0x0ZGNzLCBTT1ZPTHRkY3MsIEJUVk9MdGRjcywgU1RWT0x0ZGNzLA0KICAgICAgICAgQ0JPVk9Mb2JwY3MsIENTT1ZPTG9icGNzLCBCT1ZPTG9icGNzLCBTT1ZPTG9icGNzLCBCVFZPTG9icGNzLCBTVFZPTG9icGNzKQ0Kb2JwX2R5bmF0dHNfbm9fZGYNCmBgYA0KDQpgYGB7cn0NCm9icF9keW5hdHRzX25vX3ByaWNlX2RmIDwtIGxlZnRfam9pbihvYnBfZHluYXR0c19ub19kZiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT0JQbG90c19kZiAlPiUgc2VsZWN0KE5PLCBQUklDRSwgVFJBREVQUklDRSwgVk9MVU1FKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnk9Ik5PIikNCm9icF9keW5hdHRzX25vX3ByaWNlX2RmDQpgYGANCg0KYGBge3J9DQp0ZW1wX2RmIDwtIG9icF9keW5hdHRzX25vX2RmICU+JSANCiAgc3ByZWFkKGtleSA9IEFUVCwgdmFsdWUgPSBWQUwpICU+JSANCiAgc2VsZWN0KFRJTUUsIFRJTUVtLCBOTywgT0JQTE9UTk8sIFNPVk9MLCBTT1ZPTHRkY3MsIFNPVk9Mb2JwY3MpDQogICMgZmlsdGVyKE9CUExPVE5PID09IDEyOSkNCnRlbXBfZGYNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gdGVtcF9kZikgKyANCiAgIyBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IE5PLCB5ID0gU09WT0wpLCBjb2xvciA9ICJyZWQiKSArDQogICMgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBOTywgeSA9IFNPVk9MdGRjcyksIGNvbG9yID0gImdyZWVuIikgKw0KICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IE5PLCB5ID0gU09WT0xvYnBjcyksIGNvbG9yID0gImJsdWUiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBzbSAtIHZhbCBtZWRpYW4gYnkgc2Vjb25kDQoNCnRlbXBfc21fZGYgPC0gdGVtcF9kZiAlPiUgDQogIGdyb3VwX2J5KFRJTUVtKSAlPiUgDQogIHN1bW1hcmlzZShTT1ZPTG9icGNzID0gbWVkaWFuKFNPVk9Mb2JwY3MpKQ0KdGVtcF9zbV9kZg0KYGBgDQoNCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IHRlbXBfc21fZGYpICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gVElNRW0sIHkgPSBTT1ZPTG9icGNzKSwgY29sb3IgPSAiYmx1ZSIpDQpgYGANCg0KYGBge3J9DQpvYnBfYXR0c19ieV9vYnBfZGYgPC0gcmVhZF9jc3YoInJlc291cmNlcy80X29icF9hdHRzX2J5X29icF9kZi5jc3YiKQ0Kb2JwX2F0dHNfYnlfb2JwX2RmDQpgYGANCg0KYGBge3J9DQpvYnBfYXR0c19ieV9vYnBfZGYgJT4lIGFycmFuZ2UoZGVzYyhNSU5NQVhSQVRJTykpDQojIG9icF9hdHRzX2J5X29icF9kZiAlPiUgYXJyYW5nZShCVVlTRUxMWUlFTEQpDQpgYGANCg0KDQpgYGB7cn0NCnBiZWdpbiA8LSBvYnBfZHluYXR0c19ub19wcmljZV9kZiAlPiUgDQogIC4kREFURVRJTUVNTExTICU+JSANCiAgbWluKC4pDQpwcmludChwYmVnaW4pDQoNCnBlbmQgPC0gb2JwX2R5bmF0dHNfbm9fcHJpY2VfZGYgJT4lIA0KICAuJERBVEVUSU1FTUxMUyAlPiUgDQogIG1heCguKSANCnByaW50KHBlbmQpDQoNCnBjb2xvciA8LSBmdW5jdGlvbihhdHQsIHBsb3Rubykgew0KICBjb2xvciA9ICIiDQogIGlmIChwbG90bm8gPT0gcGxvdG5vKSB7DQogICAgaWYgKGF0dCA9PSAnQk9WT0wnKSBjb2xvciA9ICJncmVlbiINCiAgICBlbHNlIGlmIChhdHQgPT0gJ1NPVk9MJykgY29sb3IgPSAicmVkIg0KICAgIGVsc2UgaWYgKGF0dCA9PSAnQlRWT0wnIHwgYXR0ID09ICdTVFZPTCcpIGNvbG9yID0gImJsdWUiDQogICAgZWxzZSBjb2xvciA9ICJ3aGl0ZSINCiAgfSBlbHNlIHsNCiAgICBpZiAoYXR0ID09ICdCT1ZPTCcpIGNvbG9yID0gImdyZWVuIiMiYXF1YW1hcmluZSINCiAgICBlbHNlIGlmIChhdHQgPT0gJ1NPVk9MJykgY29sb3IgPSAicmVkIiMiY29yYWwiDQogICAgZWxzZSBpZiAoYXR0ID09ICdCVFZPTCcgfCBhdHQgPT0gJ1NUVk9MJykgY29sb3IgPSAiYmx1ZSIgIyJjYWRldGJsdWUxIg0KICAgIGVsc2UgY29sb3IgPSAid2hpdGUiDQogIH0NCiAgIyBwcmludChwYXN0ZShhdHQsIHBsb3RubywgY29sb3IpKQ0KICByZXR1cm4oY29sb3IpDQp9DQp0ZF9kZiA8LSBvYnBfZHluYXR0c19ub19wcmljZV9kZiAlPiUgDQogIGZpbHRlcigoREFURVRJTUVNTExTID49IHBiZWdpbiAmIERBVEVUSU1FTUxMUyA8PSBwZW5kKSAmIChBVFQgPT0gIkJPVk9MIiB8IEFUVCA9PSAiU09WT0wiIHwgQVRUID09ICJCVFZPTCIgfCBBVFQgPT0gIlNUVk9MIikgJiBQUklDRSA+IDIxNDUuMCAmIFBSSUNFIDwgMjE5NS4wKSAlPiUNCiAgbXV0YXRlKHBjb2xvciA9IG1hcDIoQVRULCBPQlBMT1ROTywgfnBjb2xvcigueCwgLnkpKSAlPiUgdW5saXN0KCkpDQp0ZF9kZg0KYGBgDQoNCmBgYHtyfQ0KIyBjdXJwbG90bm8gPSAzMDINCmN1cnBsb3RubyA9IDE4NjkNCiMgY3VycGxvdG5vID0gNTINCg0KcGJlZ2luIDwtIG9icF9keW5hdHRzX25vX3ByaWNlX2RmICU+JQ0KICBmaWx0ZXIoT0JQTE9UTk8gPT0gY3VycGxvdG5vKSAlPiUNCiAgLiREQVRFVElNRU1MTFMgJT4lDQogIG1pbiguKQ0KDQpwZW5kIDwtIG9icF9keW5hdHRzX25vX3ByaWNlX2RmICU+JQ0KICBmaWx0ZXIoT0JQTE9UTk8gPT0gY3VycGxvdG5vKSAlPiUNCiAgLiREQVRFVElNRU1MTFMgJT4lDQogIG1heCguKQ0KDQpwY29sb3IgPC0gZnVuY3Rpb24oYXR0LCBwbG90bm8pIHsNCiAgY29sb3IgPSAiIg0KICBpZiAocGxvdG5vID09IGN1cnBsb3Rubykgew0KICAgIGlmIChhdHQgPT0gJ0JPVk9MJykgY29sb3IgPSAiZ3JlZW4iDQogICAgZWxzZSBpZiAoYXR0ID09ICdTT1ZPTCcpIGNvbG9yID0gInJlZCINCiAgICBlbHNlIGlmIChhdHQgPT0gJ0JUVk9MJyB8IGF0dCA9PSAnU1RWT0wnKSBjb2xvciA9ICIjODAzMUE3IiAjImJsdWUiDQogICAgZWxzZSBjb2xvciA9ICJ3aGl0ZSINCiAgfSBlbHNlIHsNCiAgICBpZiAoYXR0ID09ICdCT1ZPTCcpIGNvbG9yID0gImFxdWFtYXJpbmUiDQogICAgZWxzZSBpZiAoYXR0ID09ICdTT1ZPTCcpIGNvbG9yID0gImNvcmFsIg0KICAgIGVsc2UgaWYgKGF0dCA9PSAnQlRWT0wnIHwgYXR0ID09ICdTVFZPTCcpIGNvbG9yID0gIiMwMDQ0ODEiICMiY2FkZXRibHVlMSINCiAgICBlbHNlIGNvbG9yID0gIndoaXRlIg0KICB9DQogICMgcHJpbnQocGFzdGUoYXR0LCBwbG90bm8sIGNvbG9yKSkNCiAgcmV0dXJuKGNvbG9yKQ0KfQ0KDQpwc2hhcGUgPC0gZnVuY3Rpb24oYXR0LCBwbG90bm8pIHsNCiAgY29sb3IgPSAiIg0KICBpZiAocGxvdG5vID09IGN1cnBsb3Rubykgew0KICAgIHNoYXBlID0gMTYNCiAgfSBlbHNlIHsNCiAgICBzaGFwZSA9IDQNCiAgfQ0KICAjIHByaW50KHBhc3RlKGF0dCwgcGxvdG5vLCBjb2xvcikpDQogIHJldHVybihzaGFwZSkNCn0NCg0KcHNpemUgPC0gZnVuY3Rpb24oYXR0LCBwbG90bm8pIHsNCiAgY29sb3IgPSAiIg0KICBpZiAocGxvdG5vID09IGN1cnBsb3Rubykgew0KICAgIHNpemUgPSAxLjANCiAgfSBlbHNlIHsNCiAgICBzaXplID0gMC41DQogIH0NCiAgIyBwcmludChwYXN0ZShhdHQsIHBsb3RubywgY29sb3IpKQ0KICByZXR1cm4oc2l6ZSkNCn0NCg0KcGxvdF9kZl93aXRob3V0X3JlcF9ieV92b2wgPC0gb2JwX2R5bmF0dHNfbm9fcHJpY2VfZGYgJT4lIA0KICBmaWx0ZXIoKERBVEVUSU1FTUxMUyA+PSBwYmVnaW4gJiBEQVRFVElNRU1MTFMgPD0gcGVuZCkgJiAoQVRUID09ICJCT1ZPTCIgfCBBVFQgPT0gIlNPVk9MIiB8IEFUVCA9PSAiQlRWT0wiIHwgQVRUID09ICJTVFZPTCIpICYgUFJJQ0UgPiAyMTQ1LjAgJiBQUklDRSA8IDIyMDUuMCkgJT4lDQogIG11dGF0ZShwY29sb3IgPSBtYXAyKEFUVCwgT0JQTE9UTk8sIH5wY29sb3IoLngsIC55KSkgJT4lIHVubGlzdCgpLA0KICAgICAgICAgcHNoYXBlID0gbWFwMihBVFQsIE9CUExPVE5PLCB+cHNoYXBlKC54LCAueSkpICU+JSB1bmxpc3QoKSwNCiAgICAgICAgIHBzaXplID0gbWFwMihBVFQsIE9CUExPVE5PLCB+cHNpemUoLngsIC55KSkgJT4lIHVubGlzdCgpKQ0KcGxvdF9kZl93aXRob3V0X3JlcF9ieV92b2wgJT4lIGZpbHRlcihPQlBMT1ROTyA9PSBjdXJwbG90bm8pDQpgYGANCg0KYGBge3J9DQojIHBsb3RfZGYgPC0gIHdpdGgocGxvdF9kZl93aXRob3V0X3JlcF9ieV92b2wsDQojICAgICAgICAgICAgICAgICAgcGxvdF9kZl93aXRob3V0X3JlcF9ieV92b2xbcmVwKDE6bnJvdyhwbG90X2RmX3dpdGhvdXRfcmVwX2J5X3ZvbCksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLmludGVnZXIobG9nKFZPTFVNRSwgYmFzZSA9IDEuMDEpKSArIDEpLF0pDQpwbG90X2RmIDwtICBwbG90X2RmX3dpdGhvdXRfcmVwX2J5X3ZvbA0KYGBgDQoNCg0KYGBge3J9DQojIGR0MSA8LSB0ZF9kZiAlPiUgZmlsdGVyKEFUVCAhPSAiQlRWT0wiICYgQVRUICE9ICJTVFZPTCIpDQojIGR0MiA8LSB0ZF9kZiAlPiUgZmlsdGVyKEFUVCA9PSAiQlRWT0wiIHwgQVRUID09ICJTVFZPTCIpDQojIGdncGxvdCgpICsgDQojICAgZ2VvbV9wb2ludChkYXRhID0gZHQxLCBtYXBwaW5nID0gYWVzKHggPSBUSU1FLCB5ID0gUFJJQ0UpLCBjb2xvciA9IGR0MSRwY29sb3IsIHNoYXBlID0gNCwgc2l6ZSA9IDAuNSkgKw0KIyAgIGdlb21fcG9pbnQoZGF0YSA9IGR0MiwgbWFwcGluZyA9IGFlcyh4ID0gVElNRSwgeSA9IFBSSUNFKSwgY29sb3IgPSBkdDIkcGNvbG9yLCBzaGFwZSA9IDQsIHNpemUgPSAwLjUpDQpgYGANCg0KYGBge3J9DQpkdDExIDwtIHBsb3RfZGYgJT4lIGZpbHRlcihPQlBMT1ROTyAhPSBjdXJwbG90bm8gJiBBVFQgIT0gIkJUVk9MIiAmIEFUVCAhPSAiU1RWT0wiKQ0KZHQxMiA8LSBwbG90X2RmICU+JSBmaWx0ZXIoT0JQTE9UTk8gIT0gY3VycGxvdG5vICYgKEFUVCA9PSAiQlRWT0wiIHwgQVRUID09ICJTVFZPTCIpKQ0KZHQyMSA8LSBwbG90X2RmICU+JSBmaWx0ZXIoT0JQTE9UTk8gPT0gY3VycGxvdG5vICYgQVRUICE9ICJCVFZPTCIgJiBBVFQgIT0gIlNUVk9MIikNCmR0MjIgPC0gcGxvdF9kZiAlPiUgZmlsdGVyKE9CUExPVE5PID09IGN1cnBsb3RubyAmIChBVFQgPT0gIkJUVk9MIiB8IEFUVCA9PSAiU1RWT0wiKSkNCmdncGxvdCgpICsgDQogIGdlb21fcG9pbnQoZGF0YSA9IGR0MTEsIG1hcHBpbmcgPSBhZXMoeCA9IFRJTUUsIHkgPSBQUklDRSksIA0KICAgICAgICAgICAgIGNvbG9yID0gZHQxMSRwY29sb3IsIHNoYXBlID0gZHQxMSRwc2hhcGUsIHNpemUgPSBkdDExJHBzaXplKSArIA0KICBnZW9tX3BvaW50KGRhdGEgPSBkdDEyLCBtYXBwaW5nID0gYWVzKHggPSBUSU1FLCB5ID0gUFJJQ0UpLCANCiAgICAgICAgICAgICBjb2xvciA9IGR0MTIkcGNvbG9yLCBzaGFwZSA9IGR0MTIkcHNoYXBlLCBzaXplID0gZHQxMiRwc2l6ZSkgKyANCiAgZ2VvbV9wb2ludChkYXRhID0gZHQyMSwgbWFwcGluZyA9IGFlcyh4ID0gVElNRSwgeSA9IFBSSUNFKSwgDQogICAgICAgICAgICAgY29sb3IgPSBkdDIxJHBjb2xvciwgc2hhcGUgPSBkdDIxJHBzaGFwZSwgc2l6ZSA9IGR0MjEkcHNpemUpICsgDQogIGdlb21fcG9pbnQoZGF0YSA9IGR0MjIsIG1hcHBpbmcgPSBhZXMoeCA9IFRJTUUsIHkgPSBQUklDRSksIA0KICAgICAgICAgICAgIGNvbG9yID0gZHQyMiRwY29sb3IsIHNoYXBlID0gZHQyMiRwc2hhcGUsIHNpemUgPSBkdDIyJHBzaXplKQ0KYGBgDQoNCmBgYHtyfQ0KZHRfcyA8LSBwbG90X2RmICU+JSBmaWx0ZXIoT0JQTE9UTk8gIT0gY3VycGxvdG5vICYgQVRUID09ICJTT1ZPTCIpDQpkdF9iIDwtIHBsb3RfZGYgJT4lIGZpbHRlcihPQlBMT1ROTyAhPSBjdXJwbG90bm8gJiBBVFQgPT0gIkJPVk9MIikNCmR0X3QgPC0gcGxvdF9kZiAlPiUgZmlsdGVyKE9CUExPVE5PICE9IGN1cnBsb3RubyAmIChBVFQgPT0gIkJUVk9MIiB8IEFUVCA9PSAiU1RWT0wiKSkNCmR0X2NwX3NiIDwtIHBsb3RfZGYgJT4lIGZpbHRlcihPQlBMT1ROTyA9PSBjdXJwbG90bm8gJiBBVFQgIT0gIkJUVk9MIiAmIEFUVCAhPSAiU1RWT0wiKQ0KZHRfY3BfdCA8LSBwbG90X2RmICU+JSBmaWx0ZXIoT0JQTE9UTk8gPT0gY3VycGxvdG5vICYgKEFUVCA9PSAiQlRWT0wiIHwgQVRUID09ICJTVFZPTCIpKQ0KDQojIGR0X3MgPC0gcGxvdF9kZiAlPiUgZmlsdGVyKEFUVCA9PSAiU09WT0wiKQ0KIyBkdF9iIDwtIHBsb3RfZGYgJT4lIGZpbHRlcihBVFQgPT0gIkJPVk9MIikNCiMgZHRfdCA8LSBwbG90X2RmICU+JSBmaWx0ZXIoQVRUID09ICJCVFZPTCIgfCBBVFQgPT0gIlNUVk9MIikNCg0KYGBgDQoNCmBgYHtyfQ0KIyBnZ3Bsb3QoZHRfcywgYWVzKHggPSBOTywgeSA9IFBSSUNFKSkgKw0KIyAgIHN0YXRfZGVuc2l0eTJkKG1hcHBpbmcgPSBhZXMoZmlsbCA9IC4ubGV2ZWwuLiksIGFscGhhID0gLjUsDQojICAgICAgICAgICAgICAgICAgZ2VvbSA9ICJwb2x5Z29uIiwgZGF0YSA9IGR0X3MpICsgDQojICAgc2NhbGVfZmlsbF92aXJpZGlzX2MoKSArIA0KIyAgICMgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ25vbmUnKSArDQojICAgc2NhbGVfZmlsbF9kaXN0aWxsZXIocGFsZXR0ZSA9ICdSZWRzJykNCmBgYA0KDQpgYGB7cn0NCiMgZ2dwbG90KGR0X2IsIGFlcyh4ID0gTk8sIHkgPSBQUklDRSkpICsNCiMgICBzdGF0X2RlbnNpdHkyZChtYXBwaW5nID0gYWVzKGZpbGwgPSAuLmxldmVsLi4pLCBhbHBoYSA9IC41LA0KIyAgICAgICAgICAgICAgICAgIGdlb20gPSAicG9seWdvbiIsIGRhdGEgPSBkdF9iKSArIA0KIyAgIHNjYWxlX2ZpbGxfdmlyaWRpc19jKCkgKyANCiMgICAjIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdub25lJykgKw0KIyAgIHNjYWxlX2ZpbGxfZGlzdGlsbGVyKHBhbGV0dGUgPSAnR3JlZW5zJykNCmBgYA0KDQoNCmBgYHtyfQ0KZ2dwbG90KGJpbmRfcm93cyh0aWJibGUoZHRfcywgZ3IgPSAicyIpLCB0aWJibGUoZHRfYiwgZ3IgPSAiYiIpKSwgYWVzKHggPSBOTywgeSA9IFBSSUNFKSkgKw0KICBzdGF0X2RlbnNpdHkyZChnZW9tID0gInBvbHlnb24iLCBhZXMoZmlsbCA9IGdyLCBhbHBoYSA9IC4ubGV2ZWwuLikpICsgDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCJzIj0iI0ZGMDAwMCIsICJiIj0iIzAwRkYwMCIpKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IGR0X3QsIG1hcHBpbmcgPSBhZXMoeCA9IE5PLCB5ID0gUFJJQ0UpLCANCiAgICAgICAgICAgICBjb2xvciA9IGR0X3QkcGNvbG9yLCBzaGFwZSA9IGR0X3QkcHNoYXBlLCBzaXplID0gZHRfdCRwc2l6ZSkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBkdF9jcF9zYiwgbWFwcGluZyA9IGFlcyh4ID0gTk8sIHkgPSBQUklDRSksIA0KICAgICAgICAgICAgIGNvbG9yID0gZHRfY3Bfc2IkcGNvbG9yLCBzaGFwZSA9IGR0X2NwX3NiJHBzaGFwZSwgc2l6ZSA9IGR0X2NwX3NiJHBzaXplKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IGR0X2NwX3QsIG1hcHBpbmcgPSBhZXMoeCA9IE5PLCB5ID0gUFJJQ0UpLCANCiAgICAgICAgICAgICBjb2xvciA9IGR0X2NwX3QkcGNvbG9yLCBzaGFwZSA9IGR0X2NwX3QkcHNoYXBlLCBzaXplID0gZHRfY3BfdCRwc2l6ZSkNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChiaW5kX3Jvd3ModGliYmxlKGR0X2IsIGdyID0gInMiKSwgdGliYmxlKGR0X3MsIGdyID0gImIiKSksIGFlcyh4ID0gTk8sIHkgPSBQUklDRSkpICsNCiAgc3RhdF9kZW5zaXR5MmQoZ2VvbSA9ICJwb2x5Z29uIiwgYWVzKGZpbGwgPSBnciwgYWxwaGEgPSAuLmxldmVsLi4pKSArIA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiYiI9IiNGRjAwMDAiLCAicyI9IiMwMEZGMDAiKSkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBkdF90LCBtYXBwaW5nID0gYWVzKHggPSBOTywgeSA9IFBSSUNFKSwgDQogICAgICAgICAgICAgY29sb3IgPSBkdF90JHBjb2xvciwgc2hhcGUgPSBkdF90JHBzaGFwZSwgc2l6ZSA9IGR0X3QkcHNpemUpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gZHRfY3Bfc2IsIG1hcHBpbmcgPSBhZXMoeCA9IE5PLCB5ID0gUFJJQ0UpLCANCiAgICAgICAgICAgICBjb2xvciA9IGR0X2NwX3NiJHBjb2xvciwgc2hhcGUgPSBkdF9jcF9zYiRwc2hhcGUsIHNpemUgPSBkdF9jcF9zYiRwc2l6ZSkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBkdF9jcF90LCBtYXBwaW5nID0gYWVzKHggPSBOTywgeSA9IFBSSUNFKSwgDQogICAgICAgICAgICAgY29sb3IgPSBkdF9jcF90JHBjb2xvciwgc2hhcGUgPSBkdF9jcF90JHBzaGFwZSwgc2l6ZSA9IGR0X2NwX3QkcHNpemUpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoYmluZF9yb3dzKHRpYmJsZShkdF9zLCBnciA9ICJzIiksIHRpYmJsZShkdF9iLCBnciA9ICJiIikpLCBhZXMoeCA9IE5PLCB5ID0gUFJJQ0UpKSArDQogIHN0YXRfZGVuc2l0eTJkKGdlb20gPSAiZGVuc2l0eTJkIiwgYWVzKGNvbG9yID0gZ3IpKSArIA0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoInMiPSIjRkYwMDAwIiwgImIiPSIjMDBGRjAwIikpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gZHRfdCwgbWFwcGluZyA9IGFlcyh4ID0gTk8sIHkgPSBQUklDRSksIA0KICAgICAgICAgICAgIGNvbG9yID0gZHRfdCRwY29sb3IsIHNoYXBlID0gZHRfdCRwc2hhcGUsIHNpemUgPSBkdF90JHBzaXplKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IGR0X2NwX3NiLCBtYXBwaW5nID0gYWVzKHggPSBOTywgeSA9IFBSSUNFKSwgDQogICAgICAgICAgICAgY29sb3IgPSBkdF9jcF9zYiRwY29sb3IsIHNoYXBlID0gZHRfY3Bfc2IkcHNoYXBlLCBzaXplID0gZHRfY3Bfc2IkcHNpemUpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gZHRfY3BfdCwgbWFwcGluZyA9IGFlcyh4ID0gTk8sIHkgPSBQUklDRSksIA0KICAgICAgICAgICAgIGNvbG9yID0gZHRfY3BfdCRwY29sb3IsIHNoYXBlID0gZHRfY3BfdCRwc2hhcGUsIHNpemUgPSBkdF9jcF90JHBzaXplKSArDQogIHRoZW1lX2J3KCkNCmBgYA0KDQpgYGB7cn0NCnRkX2ZpcnN0XzMwbWludXRlX2RmIDwtIHRkX2RmICU+JSANCiAgZmlsdGVyKFRJTUUgPCAxMTAwMDAwKQ0KdGRfZmlyc3RfMzBtaW51dGVfZGYNCmBgYA0KDQpgYGB7cn0NCnN0YXRpY19wbG90IDwtIGdncGxvdCgpICsgDQogIGdlb21fcG9pbnQoZGF0YSA9IHRkX2ZpcnN0XzMwbWludXRlX2RmLCANCiAgICAgICAgICAgICBtYXBwaW5nID0gYWVzKHggPSBUSU1FLCB5ID0gUFJJQ0UpLCANCiAgICAgICAgICAgICBjb2xvciA9IHRkX2ZpcnN0XzMwbWludXRlX2RmJHBjb2xvciwgDQogICAgICAgICAgICAgc2hhcGUgPSA0LCANCiAgICAgICAgICAgICBzaXplID0gMC41KQ0Kc3RhdGljX3Bsb3QNCmBgYA0KDQpgYGB7cn0NCmRlbnNfcGxvdCA8LSBnZ3Bsb3QodGRfZmlyc3RfMzBtaW51dGVfZGYsIGFlcyh4ID0gTk8sIHkgPSBQUklDRSkpICsNCiAgc3RhdF9kZW5zaXR5MmQoYWVzKGZpbGwgPSAuLmxldmVsLi4pLCBhbHBoYSA9IC41LA0KICAgICAgICAgICAgICAgICBnZW9tID0gInBvbHlnb24iLCBkYXRhID0gdGRfZmlyc3RfMzBtaW51dGVfZGYpICsgDQogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKCkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ25vbmUnKQ0KZGVuc19wbG90DQpgYGANCg0KYGBge3J9DQoNCmBgYA0KDQoNCmBgYHtyfQ0KIyBhbmltYXRpb24gPC0gc3RhdGljX3Bsb3QgKw0KIyAgIHRyYW5zaXRpb25fc3RhdGVzKE5PLCB0cmFuc2l0aW9uX2xlbmd0aCA9IDEsIHN0YXRlX2xlbmd0aCA9IDEpICsNCiMgICBlYXNlX2FlcygnbGluZWFyJykgKw0KIyAgIHNoYWRvd19tYXJrKCkgKw0KIyAgIHZpZXdfZm9sbG93KCkNCiMgYW5pbWF0aW9uDQpgYGANCg0KYGBge3J9DQojIG9icDMwbWluc19naWYgPC0gYW5pbWF0ZShhbmltYXRpb24sIA0KIyAgICAgICAgICAgICAgICAgIGZwcyA9IDEwLCANCiMgICAgICAgICAgICAgICAgICBkdXJhdGlvbiA9IDEwLA0KIyAgICAgICAgICAgICAgICAgIHdpZHRoID0gODAwLCBoZWlnaHQgPSA0MDAsIA0KIyAgICAgICAgICAgICAgICAgIHJlbmRlcmVyID0gZ2lmc2tpX3JlbmRlcmVyKCIuLzJnaWYvb2JwMzBtaW5zLmdpZiIpKQ0KYGBgDQoNCg==